package utils

import (
	"errors"
	"reflect"
)

// 结构体复制copy 支持二层嵌套
func StructCopy(source, target interface{}) error {
	sourceVal := reflect.ValueOf(source).Elem()
	targetVal := reflect.ValueOf(target).Elem()

	for i := 0; i < sourceVal.NumField(); i++ {
		srcField := sourceVal.Field(i)
		srcType := sourceVal.Type().Field(i)
		if srcField.Kind() == reflect.Struct {
			// Recursively copy fields from nested struct
			for j := 0; j < srcField.NumField(); j++ {
				nestedField := srcField.Field(j)
				nestedFieldType := srcField.Type().Field(j)
				dstField := targetVal.FieldByName(nestedFieldType.Name)
				if dstField.IsValid() && dstField.CanSet() && nestedField.Type() == dstField.Type() {
					dstField.Set(nestedField)
				}
			}
		} else {
			dstField := targetVal.FieldByName(srcType.Name)
			if dstField.IsValid() && dstField.CanSet() && srcField.Type() == dstField.Type() {
				dstField.Set(srcField)
			}
		}
	}
	return nil
}

// Helper function to map selected fields to a new struct
func MapFields(src interface{}, fields []string) (interface{}, error) {
	v := reflect.ValueOf(src)
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		return nil, errors.New("source must be a pointer to a struct")
	}
	v = v.Elem()
	srcType := v.Type()

	fieldMap := make(map[string]reflect.StructField)
	for i := 0; i < srcType.NumField(); i++ {
		field := srcType.Field(i)
		fieldMap[field.Name] = field
	}

	var structFields []reflect.StructField
	for _, fieldName := range fields {
		if field, found := fieldMap[fieldName]; found {
			structFields = append(structFields, field)
		}
	}

	newStruct := reflect.New(reflect.StructOf(structFields))
	newStructValue := newStruct.Elem()

	for i, field := range structFields {
		newStructValue.Field(i).Set(v.FieldByName(field.Name))
	}

	return newStruct.Interface(), nil
}
